home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / misc / Fudgit233.lha / Source / src / macro.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-14  |  24.9 KB  |  1,010 lines

  1. #include <ctype.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <signal.h>
  5. #include <setjmp.h>
  6. #include <errno.h>
  7. #ifndef NOSTDLIB_H
  8. #include <stdlib.h>
  9. #endif
  10. #ifndef NOUNISTD_H
  11. #include <unistd.h>
  12. #endif
  13. #ifndef NOMALLOC_H
  14. #include <malloc.h>
  15. #endif
  16.  
  17. #ifdef __GNUC__
  18. #ifndef alloca
  19. #define alloca __builtin_alloca
  20. #endif
  21. #else
  22. #if defined (sparc) || defined (sgi)
  23. #include <alloca.h>
  24. #endif
  25. #endif
  26.  
  27. #include "fudgit.h"
  28. #include "macro.h"
  29. #include "setshow.h"
  30. #include "readline/history.h"
  31. #include "head.h"
  32.  
  33. /* Dealing with the IO stack  */
  34.  
  35. typedef struct Iodes {
  36.     union {
  37.         FILE *fp;
  38.         char *lp;
  39.     } u;
  40.     int type;
  41.     int lino;
  42.     int iflvl;
  43.     char line[MAXMACRO];  /* contain possible emacro */
  44.     char name[TOKENSIZE];
  45. } Iodes;
  46.  
  47. static Iodes Io[MAXLEVEL];
  48. static int Iolevel = 0;
  49. static int Filelevel = 0;
  50. static char **argv;
  51. static int Working = 0;
  52.  
  53. static int checkalmac(int , char **);
  54. static int alreplace(int , char **, Macro *, char *);
  55. static int mreplace(Macro *, char **, char *), clearpop(void);
  56. static char *brkline(Iodes *, char *);
  57. static int reporterr(void);
  58. static int add_hist(char *);
  59. static int contline(char *);
  60. static FILE *curio(void);
  61.  
  62. jmp_buf Ft_Jump;
  63.  
  64. extern int hl_history_expand(char *, char **);
  65. extern void hl_add_history(char *);
  66. #ifdef AMIGA
  67. char * rl_readline(char * msgt) {
  68.     
  69.     static char lbuf[512];
  70.     printf("%s",msgt);
  71.     gets(lbuf);
  72.     
  73.     return lbuf;
  74. }
  75. #else
  76. extern char *rl_readline(char *);
  77. #endif
  78. extern int Ft_Interact;
  79.  
  80. char *Ft_nextline(char *, int *);
  81.  
  82. /* ALLOCATE ARGV */
  83.  
  84. int Ft_popio (void);
  85. int Ft_processline (char *lp);
  86. int Ft_pushio (char *string, int type, char *name);
  87. extern int Ft_ifexp (char *cline);
  88. extern int Ft_vgetargp (char *b, char **p, int type, char **add);
  89. extern int Ft_ifrun (int c, char *v);
  90. extern char *strcat (char *, const char *);
  91. extern int Ft_iflevel (void);
  92. extern int Ft_push_cwd (void);
  93. extern int Ft_pop_cwd (void);
  94. extern int Ft_clearpop_cwd (void);
  95. extern int Ft_clearpop_if (void);
  96. extern void Ft_cleanframe (void);
  97. extern int Ft_autosymremove (int level);
  98. extern int Ft_funcprocnotdef (void);
  99. extern int Ft_cleansym (void);
  100. extern int Ft_almost (char *, char *);
  101. extern int Ft_command (int , char **, char *);
  102. extern int Ft_exit (int val);
  103.  
  104. int Ft_initmac(void)
  105. {
  106.     int i;
  107.  
  108.     argv = (char **)calloc((unsigned)MAXTOKEN+1, sizeof(char *));
  109.     if (argv == (char **)NULL) {
  110.         fputs("Allocation error.\n", stderr);
  111.         exit(1);
  112.     }
  113.     for (i=0; i< MAXTOKEN;i++) {
  114.         argv[i] = (char *)calloc((unsigned)TOKENSIZE+1, sizeof(char));
  115.         if (argv[i] == (char *)NULL) {
  116.             fputs("Allocation error.\n", stderr);
  117.             exit(1);
  118.         }
  119.     }
  120.     Io[0].lino = 0;
  121.     Io[0].u.fp = stdin;
  122.     Io[0].type = AFILE;
  123.     sprintf(Io[0].name, "stdin");
  124.     return(0);
  125. }
  126.  
  127. /* THE MAIN FMODE LOOP */
  128. int Ft_run(void)
  129. {
  130.     char *cp;
  131.     int eof;
  132.  
  133.     for (;;) {
  134. #ifndef alloca
  135.         alloca(0); /* cleanup */
  136. #endif
  137.         setjmp(Ft_Jump);
  138.         Ft_Mode = FMODE;
  139.         Working = NO;
  140.         if ((cp = Ft_nextline(Ft_Prompt_fm, &eof)) == NULL) {
  141.             if (eof == -2) {
  142.                 fputs("Use 'quit' or 'exit' to exit.\n", stderr);
  143.             }
  144.             continue;
  145.         }
  146.         if (Ft_Debug & DEBUG_RAW) {
  147.             fputs(cp, stderr);
  148.         }
  149.         if (Ft_processline(cp) == ERRR) {
  150.             int Ft_processline (char *lp);
  151.             reporterr();
  152.         }
  153.     }
  154. }
  155.  
  156. int Ft_processline(char *lp)
  157. {
  158.     int argc;
  159.     char *cexp;
  160.     int check = NOTHING;
  161.  
  162.     if (Ft_ifexp(lp))
  163.         check = (QUOTES | EXPANSION | PARENTH);
  164.  
  165.     if ((argc = Ft_vgetargp(lp, argv, check, &cexp)) <= 0) { /* expand tokens */
  166.            if (argc == VERRR && !Iolevel && Ft_Interact) {
  167.             add_hist(lp);
  168.             return(0);
  169.            }
  170.            return((argc? ERRR: 0));
  171.     }
  172.     if (!Iolevel && Ft_Interact) {
  173.         add_hist(lp);
  174.     }
  175.     if ((check = checkalmac(argc, argv))) { /* expand aliases or macros */
  176.         return(check);
  177.     }
  178.     if ((check = Ft_ifrun(argc, argv[0])) == TRUE_IF) {
  179.         if (Ft_Debug & DEBUG_EXP) {
  180.             fputs(cexp, stderr);
  181.         }
  182.         Working = YES;
  183.         return(Ft_command(argc, argv, cexp));
  184.     }
  185.     return(check);
  186. }
  187.  
  188. static int checkalmac(int margc, char **margv)
  189. {
  190.     Macro *mac;
  191.     char macroline[MAXMACRO];
  192.  
  193.     if ((mac = Ft_maclook(margv[0], ANALIAS)) != 0) {  /* an alias */
  194.         if (alreplace(margc, margv, mac, macroline) == ERRR) {
  195.             return(ERRR);
  196.         }
  197.         Ft_pushio(macroline, ANALIAS, mac->name);
  198.         return(1);
  199.     }
  200.     if ((mac = Ft_maclook(margv[0], AMACRO)) != 0) {  /* a macro */
  201.         if (margc < mac->nargs + 1) {
  202.             fprintf(stderr, "%s: Missing argument.\n", mac->name);
  203.             return(ERRR);
  204.         }
  205.         if (margc > mac->nargs + 1) {
  206.             fprintf(stderr, "Warning: %s: Too many arguments.\n", mac->name);
  207.         }
  208.         if (mac->nargs > 0) {
  209.             if (mreplace(mac, margv, macroline) == ERRR) {
  210.                 return(ERRR);
  211.             }
  212.             Ft_pushio(macroline, AMACRO, mac->name);
  213.         }
  214.         else {
  215.             Ft_pushio(mac->line, AMACRO, mac->name);
  216.         }
  217.         return(1);
  218.     }
  219.     return(0);
  220. }
  221.  
  222. /* expand alias macro and keep argv[1] argv[2] ... */
  223. static int alreplace(int margc, char **margv, Macro *mac, char *out)
  224. {
  225.     int i;
  226.     int len, size;
  227.     char *cp;
  228.  
  229.     cp = out;
  230.     *cp = '\0';
  231.     size = len = strlen(mac->line);
  232.     strcat(cp, mac->line);
  233.     cp += size;
  234.     *(cp-1) = ' ';    /* remove trailing \n */
  235.     for (i=1;i<margc;i++) {
  236.         size = strlen(margv[i]);
  237.         len += size;
  238.         if (len < MAXMACRO) {
  239.             strcat(cp, margv[i]);
  240.             cp += size;
  241.             *cp++ = ' '; len++;
  242.             *cp = '\0';
  243.         }
  244.         else {
  245.             fprintf(stderr, "%s: Alias expansion too long.\n", mac->name);
  246.             return(ERRR);
  247.         }
  248.     }
  249.     *cp++ = '\n';
  250.     *cp = '\0';
  251.     return(0);
  252. }
  253.  
  254. /* replaces $1 $2 with macro arguments in argv[1] argv[2] ... */
  255. static int mreplace(Macro *mac, char **v, char *out)
  256. {
  257.     int i;
  258.     char *cp;
  259.     char *in;
  260.     int cnt = 0;
  261.  
  262.     in = mac->line;
  263.     while (*in != '\0' && cnt < MAXMACRO) {
  264.         if (*in == '$' && isdigit((int)*(in+1))) {
  265.             in++;
  266.             i = *in - '0';  
  267.             in++;
  268.             if (i>mac->nargs || i<1) {
  269.                 fprintf(stderr,
  270.                 "%s: Index %d out of range.\n", mac->name, i);
  271.                 return(ERRR);
  272.             }
  273.             cp = v[i];
  274.             while (*cp) {
  275.                 *out = *cp;
  276.                 out++; cp++;
  277.             }
  278.         }
  279.         else {
  280.             *out = *in;
  281.             out++; in++;
  282.         }
  283.         cnt++;
  284.     }
  285.     if (*in) {
  286.         fprintf(stderr, "%s: Expanded macro too long.\n", mac->name);
  287.         return(ERRR);
  288.     }
  289.     *out = '\0';
  290.     return(0);
  291. }
  292.  
  293. /* break a macro in multiple lines */
  294. static char *brkline(Iodes *iop, char *out)
  295. {
  296.     if (*(iop->u.lp) == '\0')  /* a last new line */
  297.         return(NULL);
  298.     while (*(iop->u.lp) != '\n' && *(iop->u.lp) != '\0') {
  299.         *out = *(iop->u.lp);
  300.         iop->u.lp++; out++;
  301.     }
  302.     out[0] = '\n';
  303.     out[1] = '\0';
  304.     if (*(iop->u.lp) == '\0') {
  305.         fputs("Non nl-terminated string.\n", stderr);
  306.         return(NULL);
  307.     }
  308.     else {
  309.         iop->u.lp++;
  310.         return(iop->u.lp);
  311.     }
  312. }
  313.  
  314. char *Ft_nextline(char *prompt, int *eof)
  315. {
  316.     static char buffer[LINESIZE+4];
  317.     char *buf;
  318.     int cc = 0;
  319.   
  320.     if (Ft_Interact && !Iolevel) { /* Interactive mode  */
  321.         char *cp, *out;
  322.         int expt = 0;
  323.         char *promptr = prompt;
  324.  
  325.         fflush(stdout);
  326.         fflush(stderr);
  327.         if (Ft_iflevel())
  328.             promptr = "if? ";
  329.         *eof = ERRR;
  330.         do { /* read multiple lines */
  331.             buf = buffer + cc;
  332.             if ((cp = rl_readline((buf == buffer? promptr: "? ")))) {
  333.                 *eof = 0;
  334. #ifdef AMIGA
  335.                 if (0) {
  336.                     int iexp;
  337.                     iexp = 0;
  338. #else
  339.                 if (Ft_Expandhist) {
  340.                     int iexp;
  341.                     iexp = hl_history_expand(cp, &out);
  342. #endif
  343.                     if (iexp == ERRR) { /* no history on wrong expansions */
  344.                         fprintf(stderr, "%s\n", out);
  345.                         free(out); free(cp);
  346.                         return(NULL);
  347.                     }
  348.                     expt += iexp;
  349.                     if (iexp) { /* copy expansion */
  350.                         if (buf - buffer + strlen(out) > LINESIZE) {
  351.                             fputs("Line too long.\n", stderr);
  352.                             return(NULL);
  353.                         }
  354.                         sprintf(buf, "%s\n", out);
  355.                     }
  356.                     else {
  357.                         if (buf - buffer + strlen(cp) > LINESIZE) {
  358.                             fputs("Line too long.\n", stderr);
  359.                             return(NULL);
  360.                         }
  361.                         sprintf(buf, "%s\n", cp);
  362.                     }
  363.                     free(out);
  364.                 }
  365.                 else {  /* no expansion */
  366.                     if (buf - buffer + strlen(cp) > LINESIZE) {
  367.                         fputs("Line too long.\n", stderr);
  368.                         return(NULL);
  369.                     }
  370.                     sprintf(buf, "%s\n", cp);
  371.                 }
  372. #ifndef AMIGA
  373.                 free(cp);
  374. #endif
  375.             }
  376.             else {
  377.                 *eof = -2;
  378.                 fputc('\n', stderr);
  379.                 return(NULL);
  380.             }
  381.         }  while ((cc = contline(buffer)));
  382.         if (Ft_Expandhist && expt) { /* echo expansion */
  383.                fputs(buffer, stderr);
  384.         }
  385.         return(buffer);
  386.     }
  387.  
  388.     *eof = 0;
  389.     switch(Io[Iolevel].type) {
  390.         case AFILE:
  391.             do {
  392.                 buf = buffer + cc;
  393.                 if (fgets(buf, LINESIZE - (buf-buffer),
  394.                 Io[Iolevel].u.fp) == NULL) {
  395.                     if (Io[Iolevel].iflvl != Ft_iflevel()) {
  396.                         fprintf(stderr,
  397.                         "Error: %s: Eof occurred with unmatched 'if'.\n",
  398.                         Io[Iolevel].name);
  399.                         Ft_catcher(ERRR);
  400.                     }
  401.                     *eof = 1;
  402.                     Ft_popio();
  403.                     return(NULL);
  404.                 }
  405.                 Io[Iolevel].lino++;
  406.             } while ((cc = contline(buffer)));
  407.             return(buffer);
  408.         case AMACRO:
  409.         case ANALIAS:
  410.             if (brkline(&Io[Iolevel], buffer) == NULL) {
  411.                 if (Io[Iolevel].iflvl != Ft_iflevel()) {
  412.                     fprintf(stderr,
  413.                     "Error: %s: Eom occurred with unmatched 'if'.\n",
  414.                     Io[Iolevel].name);
  415.                     Ft_catcher(ERRR);
  416.                 }
  417.                 *eof = 1;
  418.                 Ft_popio();
  419.                 return(NULL);
  420.             }
  421.             Io[Iolevel].lino++;
  422.             return(buffer);
  423.         default:
  424.             fputs("Impossible IO case.\n", stderr);
  425.             return(NULL);
  426.     }
  427. }
  428.               
  429. int Ft_pushio(char *string, int type, char *name)
  430. {
  431.     FILE *fp = 0;
  432.  
  433.     if (Iolevel + 2 >= MAXLEVEL) {
  434.         fputs("I/O stack overflow. Circular definition?\n", stderr);
  435.         if (Ft_Interact) {
  436.             fputs("Do you want to trace loop? [yn]", stderr);
  437.             if (getchar() == 'y')
  438.                 reporterr();
  439.             fflush(stdin);
  440.         }
  441.         return(ERRR);
  442.     }
  443.     switch(type) {
  444.         case ANALIAS:
  445.         case AMACRO:
  446.             Iolevel++;
  447.             strcpy(Io[Iolevel].line, string);
  448.             strcpy(Io[Iolevel].name, name);
  449.             Io[Iolevel].u.lp = Io[Iolevel].line;
  450.             break;
  451.         case AFILE:
  452.             if (strcmp(string, "-") == 0) {
  453.                 fp = stdin;
  454.             }
  455.             else {
  456. #ifdef EXTENSION
  457.                 char fname[TOKENSIZE+8];
  458.                 int len = strlen(string);
  459.  
  460.                 strcpy(fname, string);
  461.                 if (len < 3 || strcmp(fname + len - 3, EXTENSION)) {
  462.                     strcpy(fname + len, EXTENSION);
  463.                 }
  464.                 if ((fp = fopen(fname, "r")) == NULL) {
  465.                     fname[len] = '\0';
  466.                     if ((fp = fopen(fname, "r")) == NULL) {
  467.                         fprintf(stderr, "load: %s: No such file.\n", fname);
  468.                         reporterr();
  469.                         return(ERRR);
  470.                     }
  471.                 }
  472. #else
  473.                 if ((fp = fopen(string, "r")) == NULL) {
  474.                     fprintf(stderr, "load: %s: No such file.\n", string);
  475.                     reporterr();
  476.                     return(ERRR);
  477.                 }
  478. #endif
  479.             }
  480.             Ft_push_cwd();
  481.             Iolevel++;
  482.             Filelevel++;
  483.             Io[Iolevel].u.fp = fp;
  484.             strcpy(Io[Iolevel].name, string);
  485.             break;
  486.         default:
  487.             fputs("Impossible IO case.\n", stderr);
  488.             return(ERRR);
  489.     }
  490.     Io[Iolevel].lino = 0;
  491.     Io[Iolevel].iflvl = Ft_iflevel();
  492.     Io[Iolevel].type = type;
  493.     return(0);
  494. }
  495.  
  496. int Ft_popio(void)
  497. {
  498.     if (Ft_Interact && !Iolevel) {
  499.         fputs("Trying to close stdin!\n", stderr);
  500.         Ft_catcher(ERRR);
  501.     }
  502.     if (!Ft_Interact && Iolevel <= 1)
  503.         Ft_exit(0);  /* stack is empty -> exit  */
  504.     switch(Io[Iolevel].type) {
  505.         case AFILE:
  506.             if (Io[Iolevel].u.fp != stdin) {
  507.                 fclose(Io[Iolevel].u.fp);
  508.             }
  509.             Iolevel--;
  510.             Filelevel--;
  511.             Ft_pop_cwd();
  512.             break;
  513.         case ANALIAS:
  514.         case AMACRO:
  515.             Iolevel--;
  516.             break;
  517.         default:
  518.             fputs("Impossible IO case.\n", stderr);
  519.             return(ERRR);
  520.     }
  521.     return(0);
  522. }
  523.  
  524. static int clearpop(void)
  525. {
  526.     while (Iolevel)
  527.         Ft_popio();
  528.     return(0);
  529. }
  530.  
  531. static FILE *curio(void)
  532. {
  533.     if (Io[Iolevel].type == AFILE) {
  534.         return(Io[Iolevel].u.fp);
  535.     }
  536.     else {
  537.         return(NULL);
  538.     }
  539. }
  540.   
  541. /* read a while or foreach loop  */
  542. char *Ft_read_loop(char **margv, char *fprom)
  543. {
  544.     static char line[MAXMACRO];
  545.     char prompt[128];
  546.     char *cp, *ce, *cl;
  547.     int size = 0;
  548.     int osize = 0;
  549.     int prompr;
  550.     int dolevel = 1;
  551.     int i;
  552.     int margc;
  553.     int cmode = 0;
  554.     extern int Ft_Interact;
  555.  
  556.     prompr = Ft_Interact && !Iolevel;   /* Do we build a prompt ? */
  557.     if (prompr) {
  558.         sprintf(prompt, "%s? ", fprom);
  559.     }
  560.     else {
  561.         prompt[0] = '\0';
  562.     }
  563.     for (;;) {
  564.         if ((cp = Ft_nextline(prompt, &i)) == (char *)NULL) {
  565.             if (i)
  566.                 break;
  567.             if (Ft_Interact && !Iolevel && !i) {
  568.                 fputs("Line ignored, continue...\n", stderr);
  569.                 continue;
  570.             }
  571.         }
  572.         /* prepare tokens */
  573.         if ((margc = Ft_vgetargp(cp, margv, PARENTH, &cl)) <= 0)
  574.             continue;
  575.         if (margc == 1 && Ft_almost(margv[0], "cm!ode")) {
  576.             if (cmode) {
  577.                 fputs("Error: Double cmode call in loop.\n", stderr);
  578.                 return(NULL);
  579.             }
  580.             cmode = 1;
  581.         }
  582.         else if (Ft_almost(margv[0], "fm!ode")) {
  583.             if (!cmode) {
  584.                 fputs("Warning: Redundant fmode call in loop.\n", stderr);
  585.             }
  586.             cmode = 0;
  587.         }
  588.         else if (!cmode &&
  589.         (Ft_almost(margv[0], "wh!ile ") || Ft_almost(margv[0], "fore!ach "))) {
  590.             dolevel++;
  591.             if (prompr) {  /* build a prompt */
  592.                 i = dolevel;
  593.                 ce = prompt + strlen(fprom);
  594.                 while (i) {
  595.                     *ce = '?';
  596.                     ce++; i--;
  597.                 }
  598.                 *ce++ = ' ';
  599.                 *ce = '\0';
  600.             }
  601.         }
  602.         else if (Ft_almost(margv[0], "end")) {
  603.             if (margc != 1)
  604.                 fputs("Warning: Ignoring tokens following `end'.\n", stderr);
  605.             if (cmode) {
  606.                 fputs("Error: `end' statement while in cmode.\n", stderr);
  607.                 return(NULL);
  608.             }
  609.             dolevel--;
  610.             if (!dolevel) {
  611.                 line[size] = '\0';
  612.                 return(line);
  613.             }
  614.             if (prompr) {
  615.                 i = dolevel;
  616.                 ce = prompt + strlen(fprom);
  617.                 while (i) {
  618.                     *ce = '?';
  619.                     ce++; i--;
  620.                 }
  621.                 *ce = ' ';
  622.                 *ce = '\0';
  623.             }
  624.         }
  625.         size += strlen(cl);
  626.         if (size > MAXMACRO) {
  627.             fputs("Sorry, loop statements too large.\n", stderr);
  628.             return(NULL);
  629.         }
  630.         sprintf(&line[osize], "%s", cl);
  631.         osize = size;
  632.     }
  633.     if (cmode)
  634.         fprintf(stderr, "%s: Eof while still in cmode.\n", fprom);
  635.     else
  636.         fprintf(stderr, "%s: Eof occurred before `end' of loop.\n", fprom);
  637.     return(NULL);
  638. }
  639.  
  640. /* read a macro  */
  641. char *Ft_readmacro(char *prompt)
  642. {
  643.     static char line[MAXMACRO];
  644.     char *cp, *cb, *ce;
  645.     int size = 0;
  646.     int osize = 0;
  647.     int eof;
  648.  
  649.     if (Io[Iolevel].type == AMACRO) {
  650.         fputs("Cannot have imbedded definitions.\n", stderr);
  651.         return(NULL);
  652.     }
  653.     for (;;) {
  654.         if ((cp = Ft_nextline(prompt, &eof)) == (char *)NULL) {
  655.             if (eof)
  656.                 break;
  657.             if (Ft_Interact && !Iolevel) {
  658.                 fputs("Line ignored, continue...\n", stderr);
  659.             }
  660.             continue;
  661.         }
  662.         cb = ce = cp;
  663.         while (isspace(*cb)) cb++;
  664.         if (Ft_almost(cb, "st!op")) {
  665.             line[size] = '\0';
  666.             return(line);
  667.         }
  668.         while (*ce != Ft_Comchar && *ce != '\n' && *ce != '\0')
  669.             ce++;
  670.         if (*ce == Ft_Comchar) { /* get rid of it */
  671.             if (cb == ce)
  672.                 continue;
  673.             *ce++ = '\n';
  674.             *ce = '\0';
  675.         }
  676.         size += strlen(cb) + 1;
  677.         if (size > MAXMACRO) {
  678.             fputs("Sorry, too big a macro.\n", stderr);
  679.             return(NULL);
  680.         }
  681.         line[osize] = '\t';
  682.         sprintf(&line[osize+1], "%s", cb);
  683.         osize = size;
  684.     }
  685.     fputs("Eof occurred before 'stop' of macro.\n", stderr);
  686.     return(NULL);
  687. }
  688.  
  689. static int reporterr(void)
  690. {
  691.     int level;
  692.  
  693.     if (Ft_Interact && !Iolevel)
  694.         return(0);
  695.  
  696.     fputs("Error trace:\n", stderr);
  697.     for (level = 1; level <= Iolevel;level++) {
  698.         switch (Io[level].type) {
  699.         case ANALIAS:
  700.             fprintf(stderr, "\tAlias \"%s\"\n", Io[level].name);
  701.             break;
  702.         case AMACRO:
  703.             fprintf(stderr,
  704.             "\tMacro \"%s\", line %d;\n", Io[level].name, Io[level].lino);
  705.             break;
  706.         case AFILE:
  707.             fprintf(stderr,
  708.             "\tFile \"%s\", line %d;\n", Io[level].name, Io[level].lino);
  709.             break;
  710.         }
  711.     }
  712.     clearpop();
  713.     Ft_clearpop_cwd();
  714.     Ft_clearpop_if();
  715.     return(0);
  716. }
  717.  
  718. int Ft_filelevel(void)
  719. {
  720.     return(Filelevel);
  721. }
  722.  
  723. int Ft_iolevel(void)
  724. {
  725.     return(Iolevel);
  726. }
  727.  
  728. char *Ft_expandedline(char *prompt, int type, int *eof)
  729. {
  730.     int narg;
  731.     char *in, *out;
  732.     extern char **argv;
  733.  
  734.     *eof = 0;
  735.     if ((in = Ft_nextline(prompt, eof)) == NULL) {
  736.         return(NULL);
  737.     }
  738.     narg = Ft_vgetargp(in, argv, type, &out);
  739.     if (narg > 0) {
  740.         if (!Iolevel && Ft_Interact)
  741.             add_hist(in);
  742.         return(out);
  743.     }
  744.     if (narg == VERRR && !Iolevel && Ft_Interact)
  745.         add_hist(in);
  746.     return(NULL);
  747. }
  748.  
  749. SIGHANDLER Ft_catcher(int sig)
  750. {
  751.     extern int Ft_Dolevel, Ft_Inbrace, Ft_Inauto, Ft_Indef, Ft_Inproto;
  752.     extern int Working;
  753.     extern int Ft_Interact;
  754.     extern void Ft_resetindex(void);
  755.     extern FILE *Ft_Outprint;
  756.  
  757.     switch (sig) {
  758.     case SIGINT:
  759. #ifdef RESTART_SIGHANDLER 
  760.         signal(SIGINT, Ft_catcher);
  761. #endif   /* restart */
  762.         if (Ft_Interact) {
  763.             if (Working == YES) {  /* In interactive mode */
  764.                 fputs("\nAborting on request.\n", stderr);
  765.                 Ft_clearpop_cwd();
  766.             }
  767.             else
  768.                 fputs("Interupt.\n", stderr);
  769.         }
  770.         else if (!Ft_Interact) { /* In batch mode */
  771.             fputs("\nExiting on request.\n", stderr);
  772.             Ft_exit(1);
  773.         }
  774.         break;
  775.     case SIGFPE:
  776.         fputs("\nFloating point exception.\n", stderr);
  777.         if (!Ft_Interact) {
  778.             Ft_exit(1);
  779.         }
  780.         break;
  781.     case ERRR:
  782.         reporterr();
  783.         if (!Ft_Interact) {
  784.             fputs("\nFatal error, exiting...\n", stderr);
  785.             Ft_exit(1);
  786.         }
  787.         break;
  788.     case SIGHUP:
  789.         fputs("\nHangup signal received... quitting...\n", stderr);
  790.         Ft_exit(1);
  791.     case SIGQUIT:
  792.         fputs("\nQuit signal received... quitting...\n", stderr);
  793.         Ft_exit(3);
  794.     case SIGSEGV:
  795.         fputs("\nSegmentation violation signal received.\n", stderr);
  796.         Ft_exit(2);
  797. #ifdef SIGBUS
  798.     case SIGBUS:
  799.         fputs("\nBus error signal received.\n", stderr);
  800.         Ft_exit(2);
  801. #endif
  802.     case SIGILL:
  803.         fputs("\nIllegal instruction signal received.\n", stderr);
  804.         Ft_exit(2);
  805.     case SIGTSTP:
  806.         fputs("\nStop signal received.\n", stderr);
  807.         fputs("Use 'fg' to call in foreground.\n", stderr);
  808.         kill(0, SIGSTOP);
  809. #ifdef VOID_SIGHANDLER
  810.         return;
  811. #else
  812.         return(0);
  813. #endif
  814.         break;
  815.     default:
  816.         fprintf(stderr, "Unknown signal %d received.\n", sig);
  817.         Ft_exit(1);
  818.     }
  819.     /* reset check variable */
  820.     Ft_Dolevel = Ft_Indef = Ft_Inbrace = Ft_Inproto = Ft_Inauto = 0;
  821.     Ft_resetindex();
  822.     Ft_cleanframe();
  823.     Ft_autosymremove(0);
  824.     clearpop();
  825.     Ft_clearpop_if();
  826.     if (Ft_funcprocnotdef())
  827.         Ft_cleansym();
  828.     fflush(Ft_Outprint);
  829.     longjmp(Ft_Jump, 1);
  830. #ifdef VOID_SIGHANDLER
  831.     return;
  832. #else
  833.     return(0);
  834. #endif
  835. }
  836.  
  837. static int add_hist(char *line)
  838. {
  839. #ifndef AMIGA
  840.     line[strlen(line)-1] = '\0';
  841.     hl_add_history(line);
  842. #endif
  843.     return(0);
  844. }
  845.  
  846. static int contline(char *line)
  847. {
  848.     int len;
  849.  
  850.     len = strlen(line) - 2;
  851.     if (len < 0)
  852.         return(0);
  853.     if (line[len] == '\\' && line[len+1] == '\n')
  854.         return(len);
  855.     return(0);
  856. }
  857.  
  858. #include "symbol.h"
  859. #include "code.h"
  860. #include "math.tab.h"
  861.  
  862. #define MAX(u, v)  ((u>v)? u: v)
  863.  
  864. int Ft_readvar(char **argp, Symbol **sym, int *loc, int (*irange)[32], double (*range)[32], int *lines, int num, int exec, char *comname)
  865. {
  866.     register int i;
  867.     FILE *fp;
  868.     char buffer[LINESIZE];
  869.     int argn;
  870.     int max = 0;
  871.     int cont;
  872.     int line;
  873.     int nerr = 0;
  874.     int actline;
  875.     int file = 1;
  876.     extern int Ft_Interact;
  877.     extern double *Ft_Data;
  878.     extern FILE *popen(const char *, const char *);
  879.  
  880.     for (i=0;i< num;i++) {
  881.         max = MAX(max, loc[i]);  /* store maximum number  */
  882.         --loc[i];  /* convert number to index */
  883.         if (loc[i] < 0) {
  884.             fprintf(stderr, "%s: %d: Invalid column number.\n",
  885.             comname, loc[i]+1);
  886.             fputs("First column is 1!\n", stderr);
  887.             return(ERRR);
  888.         }
  889.     }
  890.     if (exec) {
  891.         errno = 0;
  892.         file = 0;
  893.         signal(SIGPIPE, SIG_DFL);
  894.         if ((fp = popen(argp[1], "r")) == (FILE *)NULL) {
  895.             fprintf(stderr, "%s: %s: Program not found.\n",
  896.             comname, argp[1]);
  897.             return(ERRR);
  898.         }
  899.         sprintf(Ft_ReadFile, "%s", argp[1]);
  900.     }
  901.     else {
  902.         file = 1;
  903.         if (strcmp(argp[1], "-") == 0) {
  904.             if ((fp = curio()) == NULL) {
  905.                 fprintf(stderr, "%s: Current input is not a file.\n", comname);
  906.                 return(ERRR);
  907.             }
  908.             sprintf(Ft_ReadFile, "stdin");
  909.             file = 0;
  910.         }
  911.         else if ((fp = fopen(argp[1], "r")) == 0) {
  912.             fprintf(stderr, "%s: %s: File not found.\n", comname, argp[1]);
  913.             return(ERRR);
  914.         }
  915.         else {
  916.             sprintf(Ft_ReadFile, "%s", argp[1]);
  917.         }
  918.     }
  919.    
  920.     line = 1;   /* one ahead  */
  921.     actline = 0;
  922.     while (fgets(buffer, LINESIZE, fp) != (char *)NULL) {
  923.         actline++;
  924.         if (actline < lines[0])
  925.             continue;
  926.         if ((argn = Ft_vgetargp(buffer, argp, NOTHING, 0)) <= 0) {
  927.             if (Ft_Debug & DEBUG_READ) {
  928.                 fprintf(stderr,
  929.                 "Warning: %s: File \"%s\": line %d ignored.\n",
  930.                 comname, Ft_ReadFile, actline);
  931.             }
  932.             else if (argn == ERRR) {
  933.                 fprintf(stderr,
  934.                 "Warning: %s: File \"%s\": line %d ignored.\n",
  935.                 comname, Ft_ReadFile, actline);
  936.             }
  937.                continue;
  938.         }
  939.         if (strcmp(argp[0], "end") == 0) {
  940.             break;
  941.         }
  942.         if (argn < max) {
  943.             fprintf(stderr,
  944.            "Warning: %s: File \"%s\": line %d ignored: Less than %d columns.\n",
  945.             comname, Ft_ReadFile, actline, max);
  946.             if (nerr++ > MAXERR) {
  947.                 fprintf(stderr,
  948.                 "%s: File \"%s\": Too many errors returning...\n",
  949.                 comname, Ft_ReadFile);
  950.                 if (file) fclose(fp);
  951.                 if (exec) { fflush(fp); pclose(fp); }
  952.                 return(ERRR);
  953.             }
  954.             continue;
  955.         }
  956.         cont = 0;
  957. #define isnumb(c)  (((c) >= '0' && (c) <= '9')    || (c) == '-' || (c) == '+' || (c) == '.')
  958.         for (i=0;i<num;i++) {
  959.             if (!isnumb(argp[loc[i]][0])) { /*  check for NaN ... */
  960.                 fprintf(stderr,
  961.                 "%s: File \"%s\" line %d: Column %d is \"%s\".\n",
  962.                 comname, Ft_ReadFile, actline, loc[i]+1, argp[loc[i]]);
  963.                 if (file) fclose(fp);
  964.                 if (exec) { fflush(fp); pclose(fp); }
  965.                 return(ERRR);
  966.             }
  967.             if (sscanf(argp[loc[i]], "%lf", &sym[i]->u.vec[line]) != 1) {
  968.                 fprintf(stderr,
  969.                 "%s: File \"%s\" line %d: Column %d unreadable.\n",
  970.                 comname, Ft_ReadFile, actline, loc[i]+1);
  971.                 if (file) fclose(fp);
  972.                 if (exec) { fflush(fp); pclose(fp); }
  973.                 return(ERRR);
  974.             }
  975.             if (irange[0][i] && sym[i]->u.vec[line] < range[0][i]) {
  976.                 cont = 1;
  977.                 break;
  978.             }
  979.             if (irange[1][i] && sym[i]->u.vec[line] > range[1][i]) {
  980.                 cont = 1;
  981.                 break;
  982.             }
  983.         }
  984.         if (actline >= lines[1])
  985.             break;
  986.         if (cont == 1)
  987.             continue;
  988.         if(line++ == Ft_Samples) {
  989.             fprintf(stderr,
  990.             "%s: File \"%s\" line %d: File too large.\n",
  991.             comname, Ft_ReadFile, actline);
  992.             fputs("Use `set samples' to enlarge capacity.\n", stderr);
  993.             if (file) fclose(fp);
  994.             if (exec) { fflush(fp); pclose(fp); }
  995.             return(ERRR);
  996.         }
  997.     }
  998.     if (file) fclose(fp);
  999.     if (exec) { fflush(fp); pclose(fp); }
  1000.     *Ft_Data = (double) (line - 1);
  1001.     for (i=0;i<num;i++) {
  1002.         sym[i]->type = VEC;
  1003.     }
  1004.     if (Ft_Interact && !Iolevel)
  1005.         fprintf(stderr, "Read %d data points from %d lines.\n",
  1006.         (int) *Ft_Data, actline);
  1007.     return(0);
  1008. }
  1009.  
  1010.